/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
 *
 */

import fse from 'fs-extra';
import path from 'path';

import { BuildArtifactConst, BuildArtifactExtension } from '../const/build-directory-const.js';
import { ProjectBuildProfile } from '../options/build/project-build-profile.js';
import { generateIntegratedHspCommand, getAppInfoByProject } from '../utils/integrated-hsp-utils.js';
import { ProcessUtils } from '../utils/process-utils.js';
import { initSignRemoteHspMap } from '../utils/remote-hsp-utils.js';

import { TargetTaskService } from './service/target-task-service.js';
import RemoteHspOpt = ProjectBuildProfile.RemoteHspOpt;
import { cloneDeep, noop } from '@baize/wdk';
import { FileSet, MetricLogType, TaskInputValue } from '@ohos/hvigor';

import { ApiVersion } from '../const/sdk-const.js';
import { OhosLogger } from '../utils/log/ohos-logger.js';
import { limitMinApiVersion } from '../utils/task-util.js';

import { TaskNames } from './common/task-names.js';
import { GlobalProjectDataService } from './service/global-project-data-service.js';
import { OhosModuleTask } from './task/ohos-module-task.js';
import { DependencyManager } from '../project/dependency/dependency-manager.js';

export class ProcessIntegratedHsp extends OhosModuleTask {
  public initTaskDepends(): void {
    // no task
  }

  protected readonly _log: OhosLogger = OhosLogger.getLogger(ProcessIntegratedHsp.name);

  protected readonly inputFile: string;

  // 回填后的integratedHsp文件夹路径
  protected readonly integratedRemoteHspDir: string;

  private readonly allRemoteHspPathMap: Map<string, RemoteHspOpt> = new Map<string, RemoteHspOpt>();

  // 继承态hsp输入list
  private readonly integratedInputList: string[] = [];

  // 继承态hsp输出list
  private readonly integratedOutputList: string[] = [];

  constructor(taskService: TargetTaskService) {
    super(taskService, TaskNames.CommonTask.PROCESS_INTEGRATED_HSP);
    this.inputFile = path.resolve(this.pathInfo.getModuleBuildOutputPath(),
      this.targetData.getModuleTargetOutputFileName('', false, BuildArtifactExtension.DOT_HSP));
    this.integratedRemoteHspDir = this.projectModel.getCacheIntegratedHspPath(this.targetData.getProduct().name);
    const moduleRemoteHspPath = this.moduleModel.getRemoteHspPath();
    const projectRemoteHspPath = this.service.getProjectModel().getRemoteHspPath();
    const dependencyManager = new DependencyManager(this.projectModel.isFaMode(), this.moduleModel, this.projectModel);
    const { npmDependencies } = dependencyManager.collectAllDependencies();
    initSignRemoteHspMap(moduleRemoteHspPath, this.allRemoteHspPathMap, npmDependencies);
    initSignRemoteHspMap(projectRemoteHspPath, this.allRemoteHspPathMap, npmDependencies);
    const integratedHspUtils = GlobalProjectDataService.getInstance().getIntegratedHspUtils();
    if (!integratedHspUtils) {
      return;
    }
    for (const remoteHspObj of this.allRemoteHspPathMap.values()) {
      if (remoteHspObj.isIntegratedHsp && integratedHspUtils.isNeedIntegrated(remoteHspObj.hspDirName)) {
        this.integratedInputList.push(remoteHspObj.hspPath);
        this.integratedOutputList.push(path.resolve(this.integratedRemoteHspDir, remoteHspObj.hspDirName));
        if (integratedHspUtils) {
          integratedHspUtils.setIntegratedRemoteHsps(cloneDeep({ ...remoteHspObj, isIntegratedHsp: false }));

          // 集成态hsp签名时需要给remoteHsp方法传递信息，如果集成态hsp改变需要重新调用remoteHsp的签名方法
          // moduleName用于判断具体哪个模块需要调用签名任务，避免出现hsp1回填hsp2签名的场景
          GlobalProjectDataService.getInstance().setNeedSignedRemoteHspMap(remoteHspObj.hspDirName, {
            hspFileName: '',
            hspDirName: '',
            version: '',
            hspPath: '',
            signedHspPath: '',
            moduleName: this.moduleModel.getName(),
            isSigned: false
          });
        }
      }
    }
  }

  declareInputs(): Map<string, TaskInputValue> {
    const inputMap = super.declareInputs();
    const { bundleName, versionCode } = getAppInfoByProject(this.projectModel);
    inputMap.set('bundleName', bundleName);
    inputMap.set('versionCode', versionCode);
    return inputMap;
  }

  declareInputFiles(): FileSet {
    return super.declareInputFiles().addEntries([
      ...this.integratedInputList,
    ], {
      isDirectory: false
    });
  }

  declareOutputFiles(): FileSet {
    const outFileSet = super.declareOutputFiles();
    outFileSet.addEntries([
      ...this.integratedOutputList
    ], { isDirectory: false });
    const currentProduct = this.targetData.getProduct().name;
    const integratedHspCachePath = path.resolve(this.projectModel.getCacheIntegratedHspPath(currentProduct),
      BuildArtifactConst.INTEGRATED_HSP_CACHE);
    outFileSet.addEntry(integratedHspCachePath, { isDirectory: false });
    return outFileSet;
  }


  protected async doTaskAction() {
    const integratedHspUtils = GlobalProjectDataService.getInstance().getIntegratedHspUtils();
    if (!integratedHspUtils) {
      return;
    }

    if (this.integratedInputList.length === 0) {
      return;
    }

    if (!limitMinApiVersion(this.targetData, ApiVersion.API_VERSION_11)) {
      this._log.printErrorExit('INTEGRATED_HSP_UNSUPPORTED_API', [this.moduleModel.getParentProject().getProfilePath()]);
    }

    for (let i = 0; i < this.integratedInputList.length; i++) {
      await this.generateIntegratedHsp(this.integratedInputList[i], this.integratedOutputList[i]);
      integratedHspUtils.changeIntegratedHspStatus(path.basename(this.integratedOutputList[i]));
    }

    integratedHspUtils.writeIntegratedHspCache();
  }

  /**
   * 调用packageTool生成integratedHsp回填后产物
   *
   * @param inputFilePath
   * @param integratedHspPath
   * @private
   */
  private async generateIntegratedHsp(inputFilePath: string, integratedHspPath: string) {
    const subTaskName = 'process remote integrated HSPcommand';
    const subDurationEvent = this.durationEvent.createSubEvent(subTaskName, '');
    subDurationEvent.start();
    if (!fse.existsSync(integratedHspPath)) {
      await fse.mkdir(integratedHspPath, { recursive: true });
    }
    const command = generateIntegratedHspCommand(this.projectModel, this.sdkInfo.getPackageTool(),
      inputFilePath, integratedHspPath);
    const inputData = {
      moduleName: this.moduleName,
      taskName: this.name,
      commandLine: command
    };
    this._log._printDebugCommand(this.sdkInfo.getPackageTool(), command);

    subDurationEvent.stop();
    subDurationEvent.setLog(subDurationEvent.getName(), MetricLogType.INFO);
    const subToolTaskName = 'submit generate integrated hsp task to work pool';
    const subToolDurationEvent = this.durationEvent.createSubEvent(subToolTaskName, '');
    subToolDurationEvent.start();

    await new ProcessUtils(inputData.moduleName, inputData.taskName)
      .submitExecutionWithoutReturn(this, this.getWorkerPool(), inputData, noop, [], subToolDurationEvent);

    subToolDurationEvent.stop();
    subToolDurationEvent.setLog(subToolTaskName, MetricLogType.INFO);
  }
}
